package com.jichaoyun.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jichaoyun.common.model.PagedResult;
import com.jichaoyun.common.utils.ExcelStyleUtils;
import com.jichaoyun.common.utils.PoiExcelStyle;
import com.jichaoyun.dao.mapper.*;
import com.jichaoyun.service.*;
import com.jichaoyun.model.entity.LowParaConfigue;
import com.jichaoyun.model.entity.Realdata;
import com.jichaoyun.model.entity.StationInfo;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.model.vo.SomeStationFlowTotal;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;



/**
* @author zhen
* @description 针对表【realData】的数据库操作Service实现
* @createDate 2023-11-16 19:42:41
*/
@Service
public class RealdataServiceImpl extends ServiceImpl<RealdataMapper, Realdata>
    implements IRealdataService {

    @Resource
    private StationInfoMapper stationInfoMapper;

    @Autowired
    private IStationInfoService stationInfoService;

    @Resource
    private RealdataMapper realdataMapper;

    @Resource
    private LowParaConfigueMapper lowParaConfigueMapper;

    @Autowired
    private LimitAlarmService limitAlarmService;

    @Autowired
    private ComErrAlarmService comErrAlarmService;

    @Autowired
    private DoorOpenAlarmService doorOpenAlarmService;

    @Autowired
    private DcAlarmService dcAlarmService;

    /**
     * 管损自定义报表时间间隔标记
     */
    private static int FLAG_MINUTE = 1;
    private static int FLAG_HOUR = 2;
    private static int FLAG_DAY = 3;

    @Override
    public Realdata getStationSingleInfoById(Integer station_no) {

        return this.baseMapper.getStationSingleInfoById(station_no);

    }

//    @Override
//    public PagedResult getSingleStationData(Integer stationNo, String start, String end) {
//        return null;
//    }

    @Override
    public List<Map<String, Object>> getRealDataById(Integer station_no) {

        return this.baseMapper.getRealDatabyId(station_no);
    }

    @Override
    public Map<String, List<Float>> getHalfHourRealData(String stationName) {

        //获取当前时间 和 30分钟前的时间 并 格式化
        LocalDateTime dateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String end = formatter.format(dateTime);
        String start = formatter.format(dateTime.minusMinutes(30));

        //根据传入的站点名称找到站点id
        Map<String, List<Float>> result = new HashMap<>();
        LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StationInfo::getStationName, stationName);
        Integer stationId = stationInfoService.getOne(wrapper).getStationNo();


        //查找30分钟前到现在的所有数据，倒序排序,只取最近的30条
        LambdaQueryWrapper<Realdata> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Realdata::getRecordTime, start).lt(Realdata::getRecordTime, end).eq(Realdata::getStation, stationId).orderByDesc(Realdata::getRealId);
        List<Realdata> list = this.baseMapper.selectList(queryWrapper);
        if (list == null) {
            throw new MyException(MyExceptiontType.Other, null);
        }

        List<Float> flowList = new ArrayList<>();
        List<Float> tempList = new ArrayList<>();
        List<Float> presList = new ArrayList<>();
        List<Float> freqList = new ArrayList<>();

        //遍历list，将数据分别写入流量、温度、压力、频率四个链表
        for (Realdata item : list) {
            flowList.add(item.getFlow());
            tempList.add(item.getTemp());
            presList.add(item.getPres());
            freqList.add(item.getFreq());
        }
        result.put("近30分钟流量", flowList);
        result.put("近30分钟温度", tempList);
        result.put("近30分钟压力", presList);
        result.put("近30分钟频率", freqList);

        return result;
    }


    @Override
    public List<Realdata> getTop5Flow() {
        List<Realdata> datalist = this.baseMapper.selectTop5Flow();
        return getRealdata(datalist);
    }

    @Override
    public List<Realdata> getTop5Temp() {
        List<Realdata> datalist = this.baseMapper.selectTop5Temp();
        return getRealdata(datalist);
    }

    @Override
    public List<Realdata> getTop5Pres() {
        List<Realdata> datalist = this.baseMapper.selectTop5Pres();
        return getRealdata(datalist);
    }

    @Override
    public PagedResult getMultiRealInfovo(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<Realdata> multiRealInfoList = this.baseMapper.getMultiRealInfo();
//
//        System.out.println(multiRealInfoList);
//        System.out.println(multiRealInfoList.size());

        for (int i = 0; i < multiRealInfoList.size(); i++) {
            Realdata multiRealInfo = multiRealInfoList.get(i);
            Integer station = multiRealInfo.getStation();
            LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StationInfo::getStationNo, station);
            StationInfo staObject = stationInfoMapper.selectOne(wrapper);
            if (staObject == null) {
                throw new MyException(MyExceptiontType.Other, null);
//                multiRealInfo.setStation_name("未知站点错误");
            } else {
                multiRealInfo.setStation_name(staObject.getStationName());
            }
        }
        PageInfo<Realdata> pagelist = new PageInfo<>(multiRealInfoList);
        PagedResult result = new PagedResult();
        result.setTotal((int) pagelist.getTotal());
        result.setPages(pagelist.getPages());
        result.setRows(pagelist.getList());
        return result;
    }


    @NotNull
    /**
     * 主要是给realdata的站名赋值
     */
    private List<Realdata> getRealdata(List<Realdata> datalist) {
        for (Realdata realdata : datalist) {
            Integer station_no = realdata.getStation();
            LambdaQueryWrapper<StationInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StationInfo::getStationNo, station_no);
            String station_name = stationInfoMapper.selectOne(lambdaQueryWrapper).getStationName();
            realdata.setStation_name(station_name);
        }
        return datalist;
    }

    /**
     * 查看各项报警占比
     *
     * @return
     */
    @Override
    public Map<String, Long> eachAlarmProportion() {
        Map<String, Long> map = new HashMap<>();

        map.putAll(limitAlarmService.eachAlarmProportion());

        map.putAll(comErrAlarmService.eachAlarmProportion());

        map.putAll(doorOpenAlarmService.eachAlarmProportion());

        map.putAll(dcAlarmService.eachAlarmProportion());

        return map;
    }

    /**
     * 查询某时间区间低计量参数的显示结果
     *
     * @param pageNo
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public PagedResult getPeriodInfoPage(Integer pageNo, LocalDateTime startTime, LocalDateTime endTime) {
        QueryWrapper<StationInfo> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("station_no");
        List<StationInfo> stationInfoList = stationInfoMapper.selectList(wrapper);
        //用来封装结果
        List<LowParaConfigue> lowParaConfigueList = new ArrayList<>();
        List<Integer> stationNoList = new ArrayList<>();
        //将站号封装到站号的list
        for (int i = 0; i < stationInfoList.size(); i++) {
            stationNoList.add(stationInfoList.get(i).getStationNo());
        }

        PageHelper.startPage(pageNo, 10);
        List<Realdata> realdataListEnd = realdataMapper.getNearFlowBeforeTime(endTime, stationNoList);

        PageHelper.startPage(pageNo, 10);
        List<Realdata> realdataListStart = realdataMapper.getNearFlowAfterTime(startTime, stationNoList);

        if (realdataListStart.isEmpty() || realdataListEnd.isEmpty()) {
            throw new MyException(MyExceptiontType.Other, null);
        }
        //封装lowParaConfigueList的结果
        for (int i = 0; i < realdataListEnd.size(); i++) {
            Float flow = realdataListEnd.get(i).getFlow() - realdataListStart.get(i).getFlow();
            LowParaConfigue lowParaConfigue = new LowParaConfigue();
            Integer station_no = realdataListEnd.get(i).getStation();
            lowParaConfigue.setStationNo(station_no);
            lowParaConfigue.setStationName(stationInfoMapper.selectById(station_no).getStationName());
            lowParaConfigue.setStartTime(startTime);
            lowParaConfigue.setEndTime(endTime);
            lowParaConfigue.setFTotal(flow);
            lowParaConfigueList.add(lowParaConfigue);
        }

        //封装分页返回结果
        PageInfo<Realdata> pageInfo = new PageInfo<>(realdataListEnd);
        PagedResult pagedResult = new PagedResult();
        pagedResult.setTotal(pageInfo.getTotal());
        pagedResult.setPages(pageInfo.getPages());
        pagedResult.setRows(lowParaConfigueList);

        return pagedResult;
    }

    /**
     * 低计量参数设置导出到excel
     *
     * @param start
     * @param end
     * @param response
     * @throws IOException
     */
    @Override
    public void getPeriodInfo(LocalDateTime start, LocalDateTime end, HttpServletResponse response) throws IOException {
        QueryWrapper<StationInfo> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("station_no");
        List<StationInfo> stationInfoList = stationInfoMapper.selectList(wrapper);
        //用来封装结果
        List<LowParaConfigue> lowParaConfigueList = new ArrayList<>();
        List<Integer> stationNoList = new ArrayList<>();
        //将站号封装到站号的list
        for (int i = 0; i < stationInfoList.size(); i++) {
            stationNoList.add(stationInfoList.get(i).getStationNo());
        }

        List<Realdata> realdataListEnd = realdataMapper.getNearFlowBeforeTime(end, stationNoList);

        List<Realdata> realdataListStart = realdataMapper.getNearFlowAfterTime(start, stationNoList);

        if (realdataListStart.isEmpty() || realdataListEnd.isEmpty()) {
            throw new MyException(MyExceptiontType.Other, null);
        }
        //封装lowParaConfigueList的结果
        for (int i = 0; i < realdataListEnd.size(); i++) {
            if (i == 167) {
                break;
            }
            Float flow = realdataListEnd.get(i).getFlow() - realdataListStart.get(i).getFlow();
            LowParaConfigue lowParaConfigue = new LowParaConfigue();
            Integer station_no = realdataListEnd.get(i).getStation();
            lowParaConfigue.setStationNo(station_no);
            lowParaConfigue.setStationName(stationInfoMapper.selectById(station_no).getStationName());
            lowParaConfigue.setStartTime(start);
            lowParaConfigue.setEndTime(end);
            lowParaConfigue.setFTotal(flow);

            QueryWrapper<LowParaConfigue> w = new QueryWrapper<>();
            w.eq("station_no", station_no).orderByDesc("id");
            List<LowParaConfigue> lowParaConfigueList1 = lowParaConfigueMapper.selectList(w);
            if (lowParaConfigueList1 == null || lowParaConfigueList1.size() == 0 || lowParaConfigueList1.get(0) == null) {
                lowParaConfigue.setFTotalAlter(null);
            } else {
                lowParaConfigue.setFTotalAlter(lowParaConfigueList1.get(0).getFTotalAlter());
                lowParaConfigue.setAlterTime(lowParaConfigueList1.get(0).getAlterTime());
            }

            lowParaConfigueList.add(lowParaConfigue);

        }
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("低计量参数导出表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(ExcelStyleUtils.getHeadStyle(), ExcelStyleUtils.getContentStyle());

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), LowParaConfigue.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("sheet1")
                    .doWrite(lowParaConfigueList);

        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");

            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSONUtils.toJSONString(map));
            throw new MyException(MyExceptiontType.FILEDOWNLOADFAIL, "下载文件失败");
        }

    }

    /**
     * 控制最大的序列大小是subsetSize
     *
     * @param originalList
     * @param subsetSize
     * @return
     */
    private List<Float> getDivSubset(List<Float> originalList, int subsetSize) {
        List<Float> selectedList = new ArrayList<>();
        int divIndex = 0;
        for (int i = 0; i < subsetSize; i++) {
            selectedList.add(originalList.get(i));
            divIndex = (int) originalList.size() * i / subsetSize;
        }
        selectedList.add(originalList.get(originalList.size() - 1));
        return selectedList;
    }

    /**
     * 对这个区间的时间也进行10等分
     *
     * @param startTime
     * @param endTime
     * @param divisions
     * @return
     */
    private static List<String> divideDateTime(LocalDateTime startTime, LocalDateTime endTime, int divisions) {
        List<String> result = new ArrayList<>();
        long totalMinutes = startTime.until(endTime, java.time.temporal.ChronoUnit.MINUTES);

        for (int i = 0; i < divisions; i++) {
            long minutesToAdd = totalMinutes * i / divisions;
            LocalDateTime dividedDateTime = startTime.plusMinutes(minutesToAdd);

            // 将时间格式化为字符串并添加到结果列表
            String formattedDateTime = dividedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
            result.add(formattedDateTime);
        }

        // 添加结束时间点
        result.add(endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));

        return result;
    }

    /**
     * 管损报表查询-查询右边的图
     * 查找某时间区间内的数据
     *
     * @return
     */
    @Override
    public Map<String, Object> getPeriodLineLossForm(Integer lineId, LocalDateTime start, LocalDateTime end) {
        HashMap<String, Object> resMap = new HashMap<>();
        List<String> pipeLossList = new ArrayList<>();
        List<String> pipeLossTimeList = new ArrayList<>();

        long betw = ChronoUnit.MINUTES.between(start, end);
        int desired_count = 600;
        int count = Math.min((int) betw, desired_count);
        List<LocalDateTime> timeNodes = getTimeNodes(start, end, count);
        int interval = 120;//时间间隔120s

        List<Integer> mainStationNos = new ArrayList<Integer>();
        float[] sumSubTotalFlowArray = new float[86400];
        float[] sumFlowArray = new float[86400];
        List<Float> subTotalFlowList = new ArrayList<>();
        List<Float> flowList = new ArrayList<>();

        if (lineId == -1) {//所有线路的管损和，所有查询出所有总表
            mainStationNos = stationInfoMapper.selectAllMainStationList();//select stationNo from stationInfo where user_type = 0 and is_use = 1
            List<Integer> lineStationNos = stationInfoMapper.selectLineOneMainStationList();//select stationNo from stationInfo where user_type = 0 and is_use = 1 groupBy lineId limit 1
            for (int stationNo : lineStationNos) {
                subTotalFlowList = realdataMapper.getSubTotalFlowListByTimeRange(start, end, interval, stationNo);
                Float[] subArray = subTotalFlowList.toArray(new Float[0]);
                for (int i = 0; i < subArray.length; i++) {
                    //subArray[i]如果空就设为0
                    if (subArray[i] == null) {
                        subArray[i] = 0f;
                    }
                    sumSubTotalFlowArray[i] += subArray[i];
                }
            }
        } else {//一条线路的管损和
            //查出这条线路的总表
            mainStationNos = stationInfoMapper.selectMainStationListByLineId(lineId);
            //mainStationNos的第一个
            int stationNo = mainStationNos.get(0);
            subTotalFlowList = realdataMapper.getSubTotalFlowListByTimeRange(start, end, interval, stationNo);
            Float[] subArray = subTotalFlowList.toArray(new Float[0]);
            for (int i = 0; i < subArray.length; i++) {
                sumSubTotalFlowArray[i] += subArray[i];
            }
        }

        for (int stationNo : mainStationNos) {
            flowList = realdataMapper.getFlowListByTimeRange(start, end, interval, stationNo);
            Float[] flowArray = flowList.toArray(new Float[0]);
            for (int i = 0; i < flowArray.length; i++) {
                sumFlowArray[i] += flowArray[i];
            }
        }
        for (int i = 0; i < count; i++) {
            pipeLossList.add(String.format("%.2f", sumSubTotalFlowArray[i] - sumFlowArray[i]));
            pipeLossTimeList.add(String.valueOf(timeNodes.get(i)));
        }

        //时间永远只显示固定的10个
        List<String> timeList = divideDateTime(start,end,10);
        if(pipeLossTimeList.size()<timeList.size()) {
            timeList = pipeLossTimeList;
        }
        resMap.put("横坐标显示的时间序列",timeList);
        resMap.put("管损数据序列",pipeLossList);
        resMap.put("管损时间序列",pipeLossTimeList);

        return resMap;

    }



//    public Map<String, Object> getPeriodLineLossForm(Integer lineId, LocalDateTime start, LocalDateTime end) {
//        HashMap<String,Object> resMap = new HashMap<>();
//        List<String> pipeLossList = new ArrayList<>();
//        List<String> pipeLossTimeList = new ArrayList<>();
//        LocalDateTime s1 = start;
//        long betw = ChronoUnit.MINUTES.between(start, end);
//        int desired_count = 600;
//        int count = Math.min((int) betw, desired_count);
//        // 生成时间节点和窗口
//        List<LocalDateTime> timeNodes = getTimeNodes(start, end, count);
//        List<TimeWindow> timeWindows = convertToTimeWindows(timeNodes, 90);
//
//        // 查询主站列表(应该也就6个)
//        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
//        wp.eq(StationInfo::getUserType, 0).eq(StationInfo::getIsUse, 1);
//        List<StationInfo> mains = stationInfoMapper.selectList(wp);
//
//
//        Map<LocalDateTime,Float> startTimeLossmap = new HashMap<>();
//        //把timeWindows.startTime作为key加到map里，初始化所有键对应的值都为0
//        for(TimeWindow timeWindow : timeWindows){
//            startTimeLossmap.put(timeWindow.startTime,0f);
//        }
//        for(StationInfo main : mains){
//            List<Map<LocalDateTime,Float>> stationLossTimewindowList = realdataMapper.batchQueryByTimeWindowsAndStation(main.getStationNo(),  timeWindows);
//            //把列表里的map根据key去startTimeLossmap里对应的key的value上
//            for(Map<LocalDateTime,Float> map : stationLossTimewindowList){
//                for(Map.Entry<LocalDateTime,Float> entry : map.entrySet()){
//                    startTimeLossmap.put(entry.getKey(),startTimeLossmap.get(entry.getKey())+entry.getValue());
//                }
//            }
//        }
//        //把startTimeLossmap里的键和值转成pipeLossTimeList和pipeLossList
//        for(Map.Entry<LocalDateTime,Float> entry : startTimeLossmap.entrySet()){
//            pipeLossTimeList.add(entry.getKey().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
//            pipeLossList.add(String.valueOf(entry.getValue()));
//        }
//        //返回结果
//        List<String> timeList = divideDateTime(s1,end,10);//时间永远只显示固定的10个
//        if(pipeLossTimeList.size()<timeList.size()) {
//            timeList = pipeLossTimeList;
//        }
//        resMap.put("横坐标显示的时间序列",timeList);
//        resMap.put("管损数据序列",pipeLossList);
//        resMap.put("管损时间序列",pipeLossTimeList);
//        return resMap;
//
//    }

//    public Map<String, Object> getPeriodLineLossForm(Integer lineId, LocalDateTime start, LocalDateTime end) {
//        HashMap<String,Object> resMap = new HashMap<>();
//        List<String> pipeLossList = new ArrayList<>();
//        List<String> pipeLossTimeList = new ArrayList<>();
//        LocalDateTime s1 = start;
//
//        if(lineId==-1){
//            long betw = ChronoUnit.MINUTES.between(start,end);
//            //这里查出这条线路的总表
//            LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
//            wp.eq(StationInfo::getUserType,0).eq(StationInfo::getIsUse, 1);
//            List<StationInfo> mains = stationInfoMapper.selectList(wp);
//
//            //给前端最多返回这么多的数据，，这里进行均等分割算法
//            int desired_count = 600;
//            List<Realdata> realdataList = new ArrayList<>();
//            if(betw > desired_count){
//                //数据挺大的，要切分显示
//                List<LocalDateTime> timeNodes = getTimeNodes(start, end, desired_count);
//                List<TimeWindow> timeWindows = convertToTimeWindows(timeNodes, 90); // 90秒为一个窗口
//
//
////                for (LocalDateTime timeNode : timeNodes) {
////                    float total = 0f;
////                    float subtotal = 0f;
////                    HashSet<Integer> visitedLine = new HashSet<>();
////                    Realdata realdata = null;
////
////                    for (StationInfo main : mains) {
////                        LocalDateTime s = timeNode;
////                        LocalDateTime e = timeNode.plusSeconds(90);
////                        realdata= realdataMapper.historySelectOne(main.getStationNo(), s, e);
////
////                        if(realdata!=null) {
////                            total+=realdata.getFlow();
////                            if(!visitedLine.contains(main.getLineId())){
////                                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
////                                subtotal+=realdata.getSubTotalFlow();
////                                visitedLine.add(main.getLineId());
////                            }
////                        } else {
////                            total+=0;
////                        }
////                    }
////                    float loss=0;
////                    if(realdata!=null){
////                        if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
////                        loss = total - subtotal;
////                    }
////                    pipeLossList.add(String.format("%.2f",loss));
////                    pipeLossTimeList.add(String.valueOf(timeNode));
////
////                }
//            }
//            else{
//                //说明执行完了，数据量应该不大，全部显示
//                while (end.compareTo(start)>0) {
//                    List<LocalDateTime> timeNodes = getTimeNodes(start, end, (int)betw);
//                    List<TimeWindow> timeWindows = convertToTimeWindows(timeNodes, 90); // 90秒为一个窗口
//                    //一次性查询出所有时间段内的（flow-sub_total_flow）和
//                    List<Float> totalPipeLossList = realdataMapper.getStationsTotalLossByTimeRange(mains,timeWindows);
//                    for(LocalDateTime startTime : timeNodes)
//                        pipeLossTimeList.add(String.valueOf(startTime));
//                    for(Float loss : totalPipeLossList)
//                        pipeLossList.add(String.format("%.2f",loss));
//
////                    start = start.plusMinutes(1);
////                    LocalDateTime e = start.plusSeconds(90);
////                    float total = 0f;
////                    float subtotal = 0f;
////                    HashSet<Integer> visitedLine = new HashSet<>();
////                    Realdata realdata = null;
////                    for (StationInfo main : mains) {
////                        realdata= realdataMapper.historySelectOne(main.getStationNo(), start, e);
////                        if(realdata!=null) {
////                            total+=realdata.getFlow();
////                            if(!visitedLine.contains(main.getLineId())){
////                                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
////                                subtotal+=realdata.getSubTotalFlow();
////                                visitedLine.add(main.getLineId());
////                            }
////                        } else {
////                            total+=0;
////                        }
////                    }
////                    float loss=0;
////                    if(realdata!=null){
////                        if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
////                        loss = total -subtotal;
////                    }
////                    pipeLossList.add(String.format("%.2f",loss));
////                    pipeLossTimeList.add(String.valueOf(start));
//                }
//            }
//
//            //时间永远只显示固定的10个
//            List<String> timeList = divideDateTime(s1,end,10);
//            if(pipeLossTimeList.size()<timeList.size()) {
//                timeList = pipeLossTimeList;
//            }
//            resMap.put("横坐标显示的时间序列",timeList);
//            resMap.put("管损数据序列",pipeLossList);
//            resMap.put("管损时间序列",pipeLossTimeList);
//
//            return resMap;
//
//        }
//
//        long betw = ChronoUnit.MINUTES.between(start,end);
//        //这里查出这条线路的总表
//        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
//        wp.eq(StationInfo::getLineId,lineId).eq(StationInfo::getUserType,0);
//        List<StationInfo> mains = stationInfoMapper.selectList(wp);
//
//        //给前端最多返回这么多的数据，，这里进行均等分割算法
//        int desired_count = 600;
//        List<Realdata> realdataList = new ArrayList<>();
//        if(betw > desired_count){
//            //数据挺大的，要切分显示
//            List<LocalDateTime> timeNodes = getTimeNodes(start, end, desired_count);
//            for (LocalDateTime timeNode : timeNodes) {
//                float total = 0f;
//                Realdata realdata = null;
//                for (StationInfo main : mains) {
//                    LocalDateTime s = timeNode;
//                    LocalDateTime e = timeNode.plusSeconds(90);
//                    realdata= realdataMapper.historySelectOne(main.getStationNo(), s, e);
//                    if(realdata!=null) {
//                        total+=realdata.getFlow();
//                    } else {
//                        total+=0;
//                    }
//                }
//                float loss=0;
//                if(realdata!=null){
//                    if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                    loss = total - realdata.getSubTotalFlow();
//                }
//                pipeLossList.add(String.format("%.2f",loss));
//                pipeLossTimeList.add(String.valueOf(timeNode));
//
//            }
//        }else{
//            //说明执行完了，数据量应该不大，全部显示
//            while (end.compareTo(start)>0) {
//                start = start.plusMinutes(1);
//                LocalDateTime e = start.plusSeconds(90);
//                float total = 0f;
//                Realdata realdata = null;
//                for (StationInfo main : mains) {
//                    realdata= realdataMapper.historySelectOne(main.getStationNo(), start, e);
//                    if(realdata!=null) {
//                        total+=realdata.getFlow();
//                    } else {
//                        total+=0;
//                    }
//                }
//                float loss=0;
//                if(realdata!=null){
//                    if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                    loss = total - realdata.getSubTotalFlow();
//                }
//                pipeLossList.add(String.format("%.2f",loss));
//                pipeLossTimeList.add(String.valueOf(start));
//            }
//        }
//
//        //时间永远只显示固定的10个
//        List<String> timeList = divideDateTime(s1,end,10);
//        if(pipeLossTimeList.size()<timeList.size()) {
//            timeList = pipeLossTimeList;
//        }
//        resMap.put("横坐标显示的时间序列",timeList);
//        resMap.put("管损数据序列",pipeLossList);
//        resMap.put("管损时间序列",pipeLossTimeList);
//
//        return resMap;
//    }


    @Override
    public Map<String, Object> getAppPeriodLineLossForm(Integer lineId, LocalDateTime start, LocalDateTime end) {
        HashMap<String, Object> resMap = new HashMap<>();
        List<String> pipeLossList = new ArrayList<>();
        List<String> pipeLossTimeList = new ArrayList<>();

        long betw = ChronoUnit.MINUTES.between(start, end);
        int desired_count = 600;
        int count = Math.min((int) betw, desired_count);
        List<LocalDateTime> timeNodes = getTimeNodes(start, end, count);
        int interval = 120;//时间间隔120s

        List<Integer> mainStationNos = new ArrayList<Integer>();
        float[] sumSubTotalFlowArray = new float[86400];
        float[] sumFlowArray = new float[86400];
        List<Float> subTotalFlowList = new ArrayList<>();
        List<Float> flowList = new ArrayList<>();

        if (lineId == -1) {//所有线路的管损和，所有查询出所有总表
            mainStationNos = stationInfoMapper.selectAllMainStationList();//select stationNo from stationInfo where user_type = 0 and is_use = 1
            List<Integer> lineStationNos = stationInfoMapper.selectLineOneMainStationList();//select stationNo from stationInfo where user_type = 0 and is_use = 1 groupBy lineId limit 1
            for (int stationNo : lineStationNos) {
                subTotalFlowList = realdataMapper.getSubTotalFlowListByTimeRange(start, end, interval, stationNo);
                Float[] subArray = subTotalFlowList.toArray(new Float[0]);
                for (int i = 0; i < subArray.length; i++) {
                    //subArray[i]如果空就设为0
                    if (subArray[i] == null) {
                        subArray[i] = 0f;
                    }
                    sumSubTotalFlowArray[i] += subArray[i];
                }
            }
        } else {//一条线路的管损和
            //查出这条线路的总表
            mainStationNos = stationInfoMapper.selectMainStationListByLineId(lineId);
            //mainStationNos的第一个
            int stationNo = mainStationNos.get(0);
            subTotalFlowList = realdataMapper.getSubTotalFlowListByTimeRange(start, end, interval, stationNo);
            Float[] subArray = subTotalFlowList.toArray(new Float[0]);
            for (int i = 0; i < subArray.length; i++) {
                sumSubTotalFlowArray[i] += subArray[i];
            }
        }

        for (int stationNo : mainStationNos) {
            flowList = realdataMapper.getFlowListByTimeRange(start, end, interval, stationNo);
            Float[] flowArray = flowList.toArray(new Float[0]);
            for (int i = 0; i < flowArray.length; i++) {
                sumFlowArray[i] += flowArray[i];
            }
        }
        for (int i = 0; i < count; i++) {
            pipeLossList.add(String.format("%.2f", sumSubTotalFlowArray[i] - sumFlowArray[i]));
            pipeLossTimeList.add(String.valueOf(timeNodes.get(i)));
        }

        //时间永远只显示固定的10个
        List<String> timeList = divideDateTime(start,end,10);
        if(pipeLossTimeList.size()<timeList.size()) {
            timeList = pipeLossTimeList;
        }
        resMap.put("横坐标显示的时间序列",timeList);
        resMap.put("管损数据序列",pipeLossList);
        resMap.put("管损时间序列",pipeLossTimeList);

        return resMap;

    }
//    public Map<String, Object> getAppPeriodLineLossForm(Integer lineId, LocalDateTime start, LocalDateTime end) {
//        HashMap<String,Object> resMap = new HashMap<>();
//        List<String> pipeLossList = new ArrayList<>();
//        List<String> pipeLossTimeList = new ArrayList<>();
//        LocalDateTime s1 = start;
//
//        ArrayList<Object> totalLossList = new ArrayList<>();
//        ArrayList<Object> subLossList = new ArrayList<>();
//        ArrayList<Object> pipeLossRateList = new ArrayList<>();
//
//        if(lineId==-1){
//            long betw = ChronoUnit.MINUTES.between(start,end);
//            //这里查出这条线路的总表
//            LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
//            wp.eq(StationInfo::getUserType,0);
//            List<StationInfo> mains = stationInfoMapper.selectList(wp);
//
//            //给前端最多返回这么多的数据，，这里进行均等分割算法
//            int desired_count = 600;
//            List<Realdata> realdataList = new ArrayList<>();
//            if(betw > desired_count){
//                //数据挺大的，要切分显示
//                List<LocalDateTime> timeNodes = getTimeNodes(start, end, desired_count);
//                for (LocalDateTime timeNode : timeNodes) {
//                    float total = 0f;
//                    float subtotal = 0f;
//                    HashSet<Integer> visitedLine = new HashSet<>();
//                    Realdata realdata = null;
//                    for (StationInfo main : mains) {
//                        LocalDateTime s = timeNode;
//                        LocalDateTime e = timeNode.plusSeconds(90);
//                        realdata= realdataMapper.historySelectOne(main.getStationNo(), s, e);
//
//                        if(realdata!=null) {
//                            total+=realdata.getFlow();
//                            if(!visitedLine.contains(main.getLineId())){
//                                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                                subtotal+=realdata.getSubTotalFlow();
//                                visitedLine.add(main.getLineId());
//                            }
//                        } else {
//                            total+=0;
//                        }
//                    }
//                    float loss=0;
//                    if(realdata!=null){
//                        if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                        loss = total - subtotal;
//                    }
//                    pipeLossList.add(String.format("%.2f",loss));
//                    pipeLossTimeList.add(String.valueOf(timeNode));
//                    if(timeNode.equals(timeNodes.get(timeNodes.size()-1))){
//                        pipeLossRateList.add(String.format("%.2f",loss*100/total));
//                        totalLossList.add(total);
//                        subLossList.add(subtotal);
//                    }
//
//                }
//            }else{
//                //说明执行完了，数据量应该不大，全部显示
//                while (end.compareTo(start)>0) {
//                    LocalDateTime e = start.plusSeconds(90);
//                    float total = 0f;
//                    float subtotal = 0f;
//                    HashSet<Integer> visitedLine = new HashSet<>();
//                    Realdata realdata = null;
//                    for (StationInfo main : mains) {
//                        realdata= realdataMapper.historySelectOne(main.getStationNo(), start, e);
//                        if(realdata!=null) {
//                            total+=realdata.getFlow();
//                            if(!visitedLine.contains(main.getLineId())){
//                                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                                subtotal+=realdata.getSubTotalFlow();
//                                visitedLine.add(main.getLineId());
//                            }
//                        } else {
//                            total+=0;
//                        }
//                    }
//                    float loss=0;
//                    if(realdata!=null){
//                        if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                        loss = total -subtotal;
//                    }
//                    pipeLossList.add(String.format("%.2f",loss));
//                    pipeLossTimeList.add(String.valueOf(start));
//                    //将最后一个时间节点的数据加入list
//                    if(start.plusMinutes(1).compareTo(end)>=0){
//                        pipeLossRateList.add(String.format("%.2f",loss*100/total));
//                        totalLossList.add(total);
//                        subLossList.add(subtotal);
//                    }
//                    start = start.plusMinutes(1);
//                }
//            }
//
//            //时间永远只显示固定的10个
//            List<String> timeList = divideDateTime(s1,end,10);
//            if(pipeLossTimeList.size()<timeList.size()) {
//                timeList = pipeLossTimeList;
//            }
//            resMap.put("横坐标显示的时间序列",timeList);
//            resMap.put("管损序列",pipeLossList);
//            resMap.put("管损时间序列",pipeLossTimeList);
//            resMap.put("管损率数据序列",pipeLossRateList);
//            resMap.put("总表流量序列",totalLossList);
//            resMap.put("分表流量序列",subLossList);
//
//            return resMap;
//
//        }
//
//        long betw = ChronoUnit.MINUTES.between(start,end);
//        //这里查出这条线路的总表
//        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
//        wp.eq(StationInfo::getLineId,lineId).eq(StationInfo::getUserType,0);
//        List<StationInfo> mains = stationInfoMapper.selectList(wp);
//
//        //给前端最多返回这么多的数据，，这里进行均等分割算法
//        int desired_count = 600;
//        List<Realdata> realdataList = new ArrayList<>();
//        if(betw > desired_count){
//            //数据挺大的，要切分显示
//            List<LocalDateTime> timeNodes = getTimeNodes(start, end, desired_count);
//            for (LocalDateTime timeNode : timeNodes) {
//                float total = 0f;
//                Realdata realdata = null;
//                for (StationInfo main : mains) {
//                    LocalDateTime s = timeNode;
//                    LocalDateTime e = timeNode.plusSeconds(90);
//                    realdata= realdataMapper.historySelectOne(main.getStationNo(), s, e);
//                    if(realdata!=null) {
//                        total+=realdata.getFlow();
//                    } else {
//                        total+=0;
//                    }
//                }
//                float loss=0;
//                if(realdata!=null){
//                    if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                    loss = total - realdata.getSubTotalFlow();
//                }
//                pipeLossList.add(String.format("%.2f",loss));
//                pipeLossTimeList.add(String.valueOf(timeNode));
//                if(timeNode.equals(timeNodes.get(timeNodes.size()-1))){
//                    pipeLossRateList.add(String.format("%.2f",loss*100/total));
//                    totalLossList.add(total);
//                    if(realdata!=null){
//                        subLossList.add(realdata.getSubTotalFlow());
//                    }
//                    else{
//                        subLossList.add(0f);
//                    }
//                }
//            }
//        }else{
//            //说明执行完了，数据量应该不大，全部显示
//            while (end.compareTo(start)>0) {
//                LocalDateTime e = start.plusSeconds(90);
//                float total = 0f;
//                Realdata realdata = null;
//                for (StationInfo main : mains) {
//                    realdata= realdataMapper.historySelectOne(main.getStationNo(), start, e);
//                    if(realdata!=null) {
//                        total+=realdata.getFlow();
//                    } else {
//                        total+=0;
//                    }
//                }
//                float loss=0;
//                if(realdata!=null){
//                    if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
//                    loss = total - realdata.getSubTotalFlow();
//                }
//                pipeLossList.add(String.format("%.2f",loss));
//                pipeLossTimeList.add(String.valueOf(start));
//                if(start.plusMinutes(1).compareTo(end)>=0){
//                    pipeLossRateList.add(String.format("%.2f",loss*100/total));
//                    totalLossList.add(total);
//                    if(realdata!=null){
//                        subLossList.add(realdata.getSubTotalFlow());
//                    }
//                    else{
//                        subLossList.add(0f);
//                    }
//                }
//                start = start.plusMinutes(1);
//            }
//        }
//
//        //时间永远只显示固定的10个
//        List<String> timeList = divideDateTime(s1,end,10);
//        if(pipeLossTimeList.size()<timeList.size()) {
//            timeList = pipeLossTimeList;
//        }
//        resMap.put("横坐标显示的时间序列",timeList);
//        resMap.put("管损序列",pipeLossList);
//        resMap.put("管损时间序列",pipeLossTimeList);
//        resMap.put("管损率数据序列",pipeLossRateList);
//        resMap.put("总表流量序列",totalLossList);
//        resMap.put("分表流量序列",subLossList);
//        return resMap;
//    }


    public static List<LocalDateTime> getTimeNodes(LocalDateTime start, LocalDateTime end, int size) {
        List<LocalDateTime> nodes = new ArrayList<>();
        // 计算区间长度
        long intervalLength = ChronoUnit.SECONDS.between(start, end);
        // 计算每个节点的间隔
        long nodeInterval = intervalLength / size;

        LocalDateTime current = start;
        for (int i = 0; i < size; i++) {
            nodes.add(current);
            current = current.plusSeconds(nodeInterval);
        }

        return nodes;
    }


    /**
     * 管损报表查询
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getLineLossForm(Integer pageNo, LocalDateTime start, LocalDateTime end ,Integer lineId) {
        PagedResult pagedResult = new PagedResult();
        List<Map<String,Object>> resMapList = new ArrayList<>();
        LocalDateTime start1 = start;

        //总路线的情况
        if(lineId==-1){
            LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
            wp.eq(StationInfo::getUserType,0);
            List<StationInfo> mains = stationInfoMapper.selectList(wp);
            long minutesBetween = ChronoUnit.MINUTES.between(start, end);
            pagedResult.setTotal(minutesBetween);
            pagedResult.setPages(minutesBetween/10+1);
            start1 = start.plusMinutes((pageNo-1)*10);

            for(int i=0;i<10;i++){
                start = start1.plusMinutes(i);
                float total = 0f;
                float subtotal = 0f;
                HashSet<Integer> visitedLine = new HashSet<>();
                Realdata realdata = new Realdata();
                for (StationInfo main : mains) {
                    //计算某个线路的总表
                    realdata = realdataMapper.historySelectOne(main.getStationNo(), start, start.plusSeconds(90));
                    if(realdata==null) {
                        total+=0;
                        continue;
                    }
                    //计算不同路线的分表的流量和
                    if(!visitedLine.contains(main.getLineId())){
                        if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                        subtotal+= realdata.getSubTotalFlow();
                        visitedLine.add(main.getLineId());
                    }
                    total+=realdata.getFlow();
                }


                HashMap<String,Object> resMap = new HashMap<>();
                resMap.put("总表流量（t/h)",total);
                resMap.put("时间",start);
                if(realdata!=null){
                    resMap.put("分表流量(t/h)",subtotal);
                    resMap.put("管损(t/h)",total-subtotal);
                    resMap.put("管损率",String.format("%.2f",(total-subtotal)*100/total));
                }else{
                    resMap.put("分表流量(t/h)","");
                    resMap.put("管损(t/h)","");
                    resMap.put("管损率","");
                }
                resMapList.add(resMap);
            }
            pagedResult.setRows(resMapList);
            return pagedResult;
        }

        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.eq(StationInfo::getLineId,lineId).eq(StationInfo::getUserType,0);
        List<StationInfo> mains = stationInfoMapper.selectList(wp);

        long minutesBetween = ChronoUnit.MINUTES.between(start, end);
        pagedResult.setTotal(minutesBetween);
        pagedResult.setPages(minutesBetween/10+1);
        start1 = start.plusMinutes((pageNo-1)*10);

        for(int i=0;i<10;i++){
            start = start1.plusMinutes(i);
            float total = 0f;
            Realdata realdata = new Realdata();
            for (StationInfo main : mains) {
                //计算某个线路的总表
                realdata = realdataMapper.historySelectOne(main.getStationNo(), start, start.plusSeconds(90));
                if(realdata==null) {
                    total+=0;
                    continue;
                }
                total+=realdata.getFlow();
            }
            HashMap<String,Object> resMap = new HashMap<>();
            resMap.put("总表流量（t/h)",total);
            resMap.put("时间",start);
            if(realdata!=null){
                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                resMap.put("分表流量(t/h)",realdata.getSubTotalFlow());
                resMap.put("管损(t/h)",total-realdata.getSubTotalFlow());
                resMap.put("管损率",String.format("%.2f",(total-realdata.getSubTotalFlow())*100/total));
            }else{
                resMap.put("分表流量(t/h)","");
                resMap.put("管损(t/h)","");
                resMap.put("管损率","");
            }
            resMapList.add(resMap);

        }

        pagedResult.setRows(resMapList);
        return pagedResult;
    }



    /**
     * 管损自定义查询
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getLineLossForm1(Integer pageNo, LocalDateTime start, LocalDateTime end ,Integer lineId) {
        PagedResult pagedResult = new PagedResult();
        List<Map<String,Object>> resMapList = new ArrayList<>();
        LocalDateTime start1 = start;
        int flag = 0;                       //时间间隔标记 1：分钟 2：小时 3：天

        //总路线的情况
        if(lineId==-1){
            LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
            wp.eq(StationInfo::getUserType,0);
            List<StationInfo> mains = stationInfoMapper.selectList(wp);
            if (end.minusHours(3).isBefore(start)){   //0-3h按分钟显示数据
                flag = FLAG_MINUTE;
                long minutesBetween = ChronoUnit.MINUTES.between(start, end);
                pagedResult.setTotal(minutesBetween);
                pagedResult.setPages(minutesBetween/10+1);
                start1 = start.plusMinutes((pageNo-1)*10);
            }else if (end.minusDays(10).isBefore(start)){   //3h-10天按小时显示数据
                flag = FLAG_HOUR;
                long hoursBetween = ChronoUnit.HOURS.between(start, end);
                pagedResult.setTotal(hoursBetween);
                pagedResult.setPages(hoursBetween/10+1);
                start1 = start.plusHours((pageNo-1)*10);
            }else {                                         //10天以上按天显示数据
                flag = FLAG_DAY;
                long daysBetween = ChronoUnit.DAYS.between(start, end);
                pagedResult.setTotal(daysBetween);
                pagedResult.setPages(daysBetween/10+1);
                start1 = start.plusDays((pageNo-1)*10);
            }

            for(int i=0;i<10;i++){
                float total = 0f;
                float subtotal = 0f;
                HashSet<Integer> visitedLine = new HashSet<>();
                Realdata realdata = new Realdata();
                if (flag == FLAG_MINUTE){
                    start = start1.plusMinutes(i);
                    for (StationInfo main : mains) {
                        //计算某个线路的总表
                        realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusSeconds(60));
                        if(realdata==null) {
                            total+=0;
                            continue;
                        }
                        //计算不同路线的分表的流量和
                        if(!visitedLine.contains(main.getLineId())){
                            if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                            subtotal+= realdata.getSubTotalFlow() / 60;   //用平均分表的流量瞬时值乘以时间得到这段时间的分表累积量
                            visitedLine.add(main.getLineId());
                        }
                        total+=realdata.getTotal();
                    }
                }else if (flag == FLAG_HOUR){
                    for (StationInfo main : mains) {
                        start = start1.plusHours(i);
                        //计算某个线路的总表
                        realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusMinutes(60));
                        if(realdata==null) {
                            total+=0;
                            continue;
                        }
                        //计算不同路线的分表的流量和
                        if(!visitedLine.contains(main.getLineId())){
                            if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                            subtotal+= realdata.getSubTotalFlow();   //用平均分表的流量瞬时值乘以时间得到这段时间的分表累积量
                            visitedLine.add(main.getLineId());
                        }
                        total+=realdata.getTotal();
                    }
                }else {
                    for (StationInfo main : mains) {
                        start = start1.plusDays(i);
                        //计算某个线路的总表
                        realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusHours(24));
                        if(realdata==null) {
                            total+=0;
                            continue;
                        }
                        //计算不同路线的分表的流量和
                        if(!visitedLine.contains(main.getLineId())){
                            if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                            subtotal+= realdata.getSubTotalFlow();   //用平均分表的流量瞬时值乘以时间得到这段时间的分表累积量
                            visitedLine.add(main.getLineId());
                        }
                        total+=realdata.getTotal();
                    }
                }



                HashMap<String,Object> resMap = new HashMap<>();
                resMap.put("总表累计量(t)",total);
                resMap.put("时间",start);
                if(realdata!=null){
                    resMap.put("分表累计量(t)",subtotal);
                    resMap.put("管损(t)",total-subtotal);
                    resMap.put("管损率",String.format("%.2f",(total-subtotal)*100/total));
                }else{
                    resMap.put("分表累计量(t)","");
                    resMap.put("管损(t)","");
                    resMap.put("管损率","");
                }
                resMapList.add(resMap);
            }
            pagedResult.setRows(resMapList);
            return pagedResult;
        }
        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.eq(StationInfo::getUserType,0);
        List<StationInfo> mains = stationInfoMapper.selectList(wp);
        if (end.minusHours(3).isBefore(start)){   //0-3h按分钟显示数据
            flag = FLAG_MINUTE;
            long minutesBetween = ChronoUnit.MINUTES.between(start, end);
            pagedResult.setTotal(minutesBetween);
            pagedResult.setPages(minutesBetween/10+1);
            start1 = start.plusMinutes((pageNo-1)*10);
        }else if (end.minusDays(10).isBefore(start)){   //3h-10天按小时显示数据
            flag = FLAG_HOUR;
            long hoursBetween = ChronoUnit.HOURS.between(start, end);
            pagedResult.setTotal(hoursBetween);
            pagedResult.setPages(hoursBetween/10+1);
            start1 = start.plusHours((pageNo-1)*10);
        }else {                                         //10天以上按天显示数据
            flag = FLAG_DAY;
            long daysBetween = ChronoUnit.DAYS.between(start, end);
            pagedResult.setTotal(daysBetween);
            pagedResult.setPages(daysBetween/10+1);
            start1 = start.plusDays((pageNo-1)*10);
        }

        for(int i=0;i<10;i++){
            float total = 0f;
            Realdata realdata = new Realdata();
            if (flag == FLAG_MINUTE){
                start = start1.plusMinutes(i);
                for (StationInfo main : mains) {
                    //计算某个线路的总表
                    realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusSeconds(60));
                    if(realdata==null) {
                        total+=0;
                        continue;
                    }
                    total+=realdata.getTotal();
                }
            }else if (flag == FLAG_HOUR){
                start = start1.plusHours(i);
                for (StationInfo main : mains) {
                    //计算某个线路的总表
                    realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusMinutes(60));
                    if(realdata==null) {
                        total+=0;
                        continue;
                    }
                    total+=realdata.getTotal();
                }
            }else {
                start = start1.plusDays(i);
                for (StationInfo main : mains) {
                    //计算某个线路的总表
                    realdata = realdataMapper.historySelectOne1(main.getStationNo(), start, start.plusDays(1));
                    if(realdata==null) {
                        total+=0;
                        continue;
                    }
                    total+=realdata.getTotal();
                }
            }

            HashMap<String,Object> resMap = new HashMap<>();
            resMap.put("总表累计量(t)",total);
            resMap.put("时间",start);
            if(realdata!=null){
                if(realdata.getSubTotalFlow()==null) realdata.setSubTotalFlow(0f);
                resMap.put("分表累计量(t)",realdata.getSubTotalFlow());
                resMap.put("管损(t)",total-realdata.getSubTotalFlow());
                resMap.put("管损率",String.format("%.2f",(total-realdata.getSubTotalFlow())*100/total));
            }else{
                resMap.put("分表累计量(t)","");
                resMap.put("管损(t)","");
                resMap.put("管损率","");
            }
            resMapList.add(resMap);

        }

        pagedResult.setRows(resMapList);
        return pagedResult;
    }


    public String calculateMinuteLossRareByStation(LocalDateTime time, Integer stationNo ,Float mainFlow){
        //查出其子节点表
        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.eq(StationInfo::getFatherStationNo,stationNo);
        List<StationInfo> divStation= stationInfoMapper.selectList(wp);

        //计算分表的流量和
        Float div_f = 0f;
        LocalDateTime start1 = time.withSecond(0);
        LocalDateTime end1= time.withSecond(0).plusSeconds(59);
        for (StationInfo stationInfo : divStation) {
            LambdaQueryWrapper<Realdata> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.le(Realdata::getRecordTime,end1).ge(Realdata::getRecordTime,start1)
                    .eq(Realdata::getStation,stationInfo.getStationNo()).orderByDesc(Realdata::getRealId);
            Realdata one = realdataMapper.selectOne(wrapper2);
            if (one == null){
                div_f+=0f;
            }else {
                div_f+=one.getFlow();
            }
        }
        return String.format("%.2f",(mainFlow-div_f)*100/mainFlow)+"%";

    }

    @Override
    public Map<String, Object> getTenMinutesLineLossForm(Integer stationNo) {
        LocalDateTime start = LocalDateTime.now().minusMinutes(11);
        HashMap<String, Object> resMap = new HashMap<>();
        LocalDateTime end = LocalDateTime.now();
        LambdaQueryWrapper<Realdata> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.le(Realdata::getRecordTime,end).ge(Realdata::getRecordTime,start)
                .eq(Realdata::getStation,stationNo).orderByDesc(Realdata::getRealId);
        List<Realdata> realdataList = realdataMapper.selectList(wrapper2);
        int i  = 0;
        for (Realdata realdata : realdataList) {
            if(i==10) {
                break;
            }
            LocalDateTime time = realdata.getRecordTime();
            String loss = calculateMinuteLossRareByStation(time, stationNo, realdata.getFlow());

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
            // 格式化时间
            String formattedTime = time.format(formatter);

            resMap.put(formattedTime,loss);
            i++;

        }

        return resMap;
    }

    /**
     * 查询任意区间的蒸汽的压力温度频率流量的数据
     *
     * @param stationNo
     * @return
     */
    @Override
    public Map<String, Object> getAnyPeriodRealData(Integer stationNo,LocalDateTime start,LocalDateTime end) {
        //子线程同步执行任务的方式去获取要取的数据的长度
        LocalDateTime finalStart = start;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                realdataMapper.historySelectCount(stationNo, finalStart, end);
            }
        });
        thread.start();

        // 主线程等待1秒,如果1s都没有完成，那么说明数据很大，到达desired_count的上限，那么就切分
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        List<Realdata> realdataList = new ArrayList<>();
        //给前端最多返回这么多的数据，，这里进行均等分割算法
        int desired_count = 1000;

        if(thread.isAlive()){
            //说明程序还在跑，数据挺大的，要切分显示
            List<LocalDateTime> timeNodes = getTimeNodes(start, end, desired_count);
            for (LocalDateTime timeNode : timeNodes) {
                LocalDateTime s = timeNode;
                LocalDateTime e = timeNode.plusSeconds(60);
                List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, s, e);
                if(realdataList1.size()!=0){
                    realdataList.add(realdataList1.get(0));
                }else{
                    Realdata realdata = new Realdata();
                    realdata.setFlow(0f);
                    realdata.setTemp(0f);
                    realdata.setPres(0f);
                    realdata.setFreq(0f);
                    realdata.setRecordTime(timeNode);
                    realdataList.add(realdata);
                }
            }
        }else{
            //说明执行完了，数据量应该不大，全部显示
//            realdataList= realdataMapper.historySelect(stationNo,start,end);
            LocalDateTime s1 = start;
            LocalDateTime e1 = end;
            while(e1.compareTo(s1)>0) {
                List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, s1, s1.plusMinutes(1));
                if(realdataList1.size()!=0){
                    realdataList.add(realdataList1.get(0));
                }else{
                    Realdata realdata = new Realdata();
                    realdata.setFlow(0f);
                    realdata.setTemp(0f);
                    realdata.setPres(0f);
                    realdata.setFreq(0f);
                    realdata.setRecordTime(s1);
                    realdataList.add(realdata);
                }
                s1 = s1.plusSeconds(30);
            }
        }


        //根据传入的站点名称找到站点id
        Map<String, Object> result = new HashMap<>();

        List<Float> flowList = new ArrayList<>();
        List<Float> tempList = new ArrayList<>();
        List<Float> presList = new ArrayList<>();
        List<Float> freqList = new ArrayList<>();
        List<String> timeList = new ArrayList<>();

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for(Realdata realdata : realdataList){
            LocalDateTime time = realdata.getRecordTime();
            flowList.add(realdata.getFlow());
            tempList.add(realdata.getTemp());
            presList.add(realdata.getPres());
            freqList.add(realdata.getFreq());
            timeList.add(time.format(dateTimeFormatter));
        }
        result.put("选择区间的流量", flowList);
        result.put("选择区间的温度", tempList);
        result.put("选择区间的压力", presList);
        result.put("选择区间的频率", freqList);
        result.put("选择区间的数据对应的时间点", timeList);

        //时间永远只显示固定的10个

        List<String> timeList2 = divideDateTime(start,end,10);
        if(timeList.size()<timeList2.size()) {
            timeList2 = timeList;
        }

        result.put("横坐标显示时间",timeList2);

        return result;
    }

    /**
     * 多用户自定义用量报表
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getTablePeriod(Integer pageNo,LocalDateTime start,LocalDateTime end) {
        PagedResult pagedResult = new PagedResult();

        Page<StationInfo> page = new Page<>(pageNo, 10);
        LambdaQueryWrapper<StationInfo> wp1 = new LambdaQueryWrapper<>();
        wp1.eq(StationInfo::getIsUse,true).orderByAsc(StationInfo::getStationNo);
        //wp1为null会报错
        page = stationInfoMapper.selectPage(page, wp1);
        List<StationInfo> records = page.getRecords();
        pagedResult.setTotal(page.getTotal());
        pagedResult.setPages(page.getPages());
        ArrayList<Map<String,Object>> res = new ArrayList<>();
        List<Integer> stations = records.stream().map(StationInfo::getStationNo).collect(Collectors.toList());
        System.out.println("第一次开始请求sharding" + new Date());
        List<Realdata> history_start = realdataMapper.historySelectAll(stations, start, start.plusMinutes(5));
        System.out.println("第一次结束请求sharding第二次开始" + new Date());
        List<Realdata> history_end = realdataMapper.historySelectAll(stations, end.plusMinutes(1), end.plusMinutes(5));
        System.out.println("第二次结束请求sharding"+ new Date());
        Map<Integer, Realdata> start_map = history_start.stream().collect(Collectors.toMap(
                Realdata::getStation,
                realdata -> realdata));
        Map<Integer, Realdata> end_map = history_end.stream().collect(Collectors.toMap(
                Realdata::getStation,
                realdata -> realdata));
        for (StationInfo record : records) {
            HashMap<String, Object> map = new LinkedHashMap<>();
            map.put("站号",record.getStationNo());
            map.put("用户名",record.getStationName());
            Realdata realdata1 =start_map.get(record.getStationNo());
            if(realdata1==null){
                map.put("起始仪表总数","--");
            }else{
                map.put("起始仪表总数",realdata1.getTotal());
            }

            Realdata realdata2 =end_map.get(record.getStationNo());
            if(realdata2==null){
                map.put("终止仪表总数","--");
            }else {
                map.put("终止仪表总数",realdata2.getTotal());
            }
            Float total = 0f;
            if(realdata1!=null && realdata2!=null && realdata1.getTotal()!=null && realdata2.getTotal()!=null){
                total = realdata2.getTotal() - realdata1.getTotal();
                map.put("区间用量",total);
            }else{
                map.put("终止仪表总数","--");
            }
            //查找管损和管损率
            if(realdata1==null || realdata2==null || realdata1.getTotal()==null || realdata2.getTotal()==null){
                map.put("管损","--");
                map.put("管损率","--");
            }

            if(record.getUserType()==0){
                //查询其子节点这段时间的消耗总量
                Float subTotal =0f;
                LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
                wp.eq(StationInfo::getUserType,1).eq(StationInfo::getLineId,record.getLineId());
                List<StationInfo> subs = stationInfoMapper.selectList(wp);
                List<Integer> no_list = subs.stream().map(StationInfo::getStationNo).collect(Collectors.toList());
                Float total_start = realdataMapper.getSubTotal(no_list,start,start.plusMinutes(5));
                Float total_end = realdataMapper.getSubTotal(no_list,end,end.plusMinutes(5));
                if(total_start==null || total_end==null){
                    map.put("管损",null);
                    map.put("管损率",null);
                }else{
                    subTotal = total_end-total_start;
//                subTotal = new Float(0.0);
//                for (StationInfo sub : subs) {
//                    Integer subNo = sub.getStationNo();
//                    Realdata sub1 = realdataMapper.historySelectOne(subNo, start, start.plusMinutes(5));
//                    if(sub1==null){
//                        continue;
//                    }
//                    Realdata sub2 = realdataMapper.historySelectOne(subNo, end.minusMinutes(1), end.plusMinutes(5));
//                    if(sub2==null){
//                        continue;
//                    }
//                    subTotal +=(sub2.getTotal()-sub1.getTotal());
//                }
                    //查找该分节点的消耗总结,相减计算管损和管损率
                    float loss = total - subTotal;
                    map.put("管损",String.format("%.2f",loss));
                    if (total!=0f){
                        map.put("管损率",String.format("%.2f",loss*100/total) +"%");
                    }else{
                        map.put("管损率","--");
                    }
                }
            }else{
                map.put("管损",null);
                map.put("管损率",null);
            }
            res.add(map);
        }
        pagedResult.setRows(res);
        return pagedResult;
    }

    @Override
    public PagedResult getThreeTablePeriodDetail(Integer pageNo,Integer pageSize,String type, LocalDateTime start, LocalDateTime end) {
        PagedResult pagedResult = new PagedResult();
        List<Integer> threeStationHighNo = new ArrayList<>(java.util.Arrays.asList(331, 350, 458));
        List<Integer> threeStationLowNo = new ArrayList<>(java.util.Arrays.asList(332, 351));
        List<Integer> threeStationNo = new ArrayList<>(java.util.Arrays.asList(331, 350, 458,332, 351));
        LambdaQueryWrapper<StationInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StationInfo::getLineId,24)
                .notIn(StationInfo::getStationNo,threeStationNo);
        List<Integer> elseStationNoHighs = stationInfoMapper.selectList(queryWrapper).stream().map(StationInfo::getStationNo).collect(Collectors.toList());

        LambdaQueryWrapper<StationInfo> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(StationInfo::getLineId,25)
                .notIn(StationInfo::getStationNo,threeStationNo);
        List<Integer> elseStationNoLows = stationInfoMapper.selectList(queryWrapper1).stream().map(StationInfo::getStationNo).collect(Collectors.toList());


        Duration between = Duration.between(start, end);
        pagedResult.setPages((between.toMinutes() / pageSize )+ (between.toMinutes() % pageSize / pageSize));
        pagedResult.setTotal(between.toMinutes());

        start = start.plusMinutes((long) pageSize * (pageNo - 1));
        List<HashMap<String, Object>> res = new ArrayList<>();

        if (Objects.equals(type, "电厂合计流量（高压）")) {

            for(long i = 0L; i < 10L; i ++){
                if(start.plusMinutes(i).isAfter(end)) break;

                HashMap<String, Object> map = new HashMap<>();
                List<Realdata> realdatas = realdataMapper.selectListInSomeStation(threeStationHighNo,start.plusMinutes(i),start.plusMinutes(i + 1));

                Map<Integer, Realdata> latestRecordsByStation = new HashMap<>();
                for (Realdata dataCache : realdatas) {
                    Integer stationNo = dataCache.getStation();
                    if (!latestRecordsByStation.containsKey(stationNo) ||
                            dataCache.getRecordTime().isAfter(latestRecordsByStation.get(stationNo).getRecordTime())) {
                        latestRecordsByStation.put(stationNo, dataCache);
                    }
                }
                float total = 0F;

                // 从Map中提取最新的记录列表
                List<Realdata> filteredRealdatas = new ArrayList<>(latestRecordsByStation.values());
                for(Realdata realdata: filteredRealdatas){
                    if(realdata.getFlow() != null){
                        total+=realdata.getFlow();
                    }
                }
                map.put("名称","电厂合计流量（高压）");
                map.put("瞬时流量",total);
                map.put("时间",start.plusMinutes(i));
                res.add(map);
            }

        } else if (Objects.equals(type, "电厂合计流量（低压）")) {

            for(long i = 0L; i < 10L; i ++){
                if(start.plusMinutes(i).isAfter(end)) break;

                HashMap<String, Object> map = new HashMap<>();
                List<Realdata> realdatas = realdataMapper.selectListInSomeStation(threeStationLowNo,start.plusMinutes(i),start.plusMinutes(i + 1));

                Map<Integer, Realdata> latestRecordsByStation = new HashMap<>();
                for (Realdata dataCache : realdatas) {
                    Integer stationNo = dataCache.getStation();
                    if (!latestRecordsByStation.containsKey(stationNo) ||
                            dataCache.getRecordTime().isAfter(latestRecordsByStation.get(stationNo).getRecordTime())) {
                        latestRecordsByStation.put(stationNo, dataCache);
                    }
                }
                float total = 0F;

                // 从Map中提取最新的记录列表
                List<Realdata> filteredRealdatas = new ArrayList<>(latestRecordsByStation.values());
                for(Realdata realdata: filteredRealdatas){
                    if(realdata.getFlow() != null){
                        total+=realdata.getFlow();
                    }
                }
                map.put("名称","电厂合计流量（低压）");
                map.put("瞬时流量",total);
                map.put("时间",start.plusMinutes(i));
                res.add(map);
            }

        }else if (Objects.equals(type, "所有用户合计流量（高压）")) {

            for(long i = 0L; i < 10L; i ++){
                if(start.plusMinutes(i).isAfter(end)) break;

                HashMap<String, Object> map = new HashMap<>();
                List<Realdata> realdatas = realdataMapper.selectListInSomeStation(elseStationNoHighs,start.plusMinutes(i),start.plusMinutes(i + 1));

                Map<Integer, Realdata> latestRecordsByStation = new HashMap<>();
                for (Realdata dataCache : realdatas) {
                    Integer stationNo = dataCache.getStation();
                    if (!latestRecordsByStation.containsKey(stationNo) ||
                            dataCache.getRecordTime().isAfter(latestRecordsByStation.get(stationNo).getRecordTime())) {
                        latestRecordsByStation.put(stationNo, dataCache);
                    }
                }
                float total = 0F;

                // 从Map中提取最新的记录列表
                List<Realdata> filteredRealdatas = new ArrayList<>(latestRecordsByStation.values());
                for(Realdata realdata: filteredRealdatas){
                    if(realdata.getFlow() != null){
                        total+=realdata.getFlow();
                    }
                }
                map.put("名称","所有用户合计流量（高压）");
                map.put("瞬时流量",total);
                map.put("时间",start.plusMinutes(i));
                res.add(map);
            }

        }
        else if (Objects.equals(type, "所有用户合计流量（低压）")) {

            for(long i = 0L; i < 10L; i ++){
                if(start.plusMinutes(i).isAfter(end)) break;

                HashMap<String, Object> map = new HashMap<>();
                List<Realdata> realdatas = realdataMapper.selectListInSomeStation(elseStationNoLows,start.plusMinutes(i),start.plusMinutes(i + 1));

                Map<Integer, Realdata> latestRecordsByStation = new HashMap<>();
                for (Realdata dataCache : realdatas) {
                    Integer stationNo = dataCache.getStation();
                    if (!latestRecordsByStation.containsKey(stationNo) ||
                            dataCache.getRecordTime().isAfter(latestRecordsByStation.get(stationNo).getRecordTime())) {
                        latestRecordsByStation.put(stationNo, dataCache);
                    }
                }
                float total = 0F;

                // 从Map中提取最新的记录列表
                List<Realdata> filteredRealdatas = new ArrayList<>(latestRecordsByStation.values());
                for(Realdata realdata: filteredRealdatas){
                    if(realdata.getFlow() != null){
                        total+=realdata.getFlow();
                    }
                }
                map.put("名称","所有用户合计流量（低压）");
                map.put("瞬时流量",total);
                map.put("时间",start.plusMinutes(i));
                res.add(map);
            }
        }

        pagedResult.setRows(res);
        return pagedResult;
    }

    @Override
    public void getTablePeriodExcel(LocalDateTime start, LocalDateTime end,HttpServletResponse response) throws IOException {

        LambdaQueryWrapper<StationInfo> wp1 = new LambdaQueryWrapper<>();
        wp1.eq(StationInfo::getIsUse,true).orderByAsc(StationInfo::getStationNo)
                .notIn(StationInfo::getStationNo,Arrays.asList(318,319,320,321,322,326,327,328,329,330));
        //wp1为null会报错
        List<StationInfo> records = stationInfoMapper.selectList(wp1);
        ArrayList<Map<String,Object>> res = new ArrayList<>();
        for (StationInfo record : records) {
            HashMap<String, Object> map = new LinkedHashMap<>();
            map.put("站号",record.getStationNo());
            map.put("用户名",record.getStationName());
            Realdata realdata1 = realdataMapper.historySelectOne(record.getStationNo(), start, start.plusMinutes(5));
            if(realdata1==null){
                map.put("起始仪表总数","--");
            }else{
                map.put("起始仪表总数",realdata1.getTotal());
            }

            Realdata realdata2 = realdataMapper.historySelectOne(record.getStationNo(), end.minusMinutes(1), end.plusMinutes(5));
            if(realdata2==null){
                map.put("终止仪表总数","--");
            }else {
                map.put("终止仪表总数",realdata2.getTotal());
            }
            Float total = 0f;
            if(realdata1!=null && realdata2!=null){
                total = realdata2.getTotal() - realdata1.getTotal();
                map.put("区间用量",total);
            }else{
                map.put("终止仪表总数","--");
            }
            //查找管损和管损率
            if(realdata1==null || realdata2==null){
                map.put("管损","--");
                map.put("管损率","--");
            }

            if(record.getUserType()==0){
                //查询其子节点这段时间的消耗总量
                Float subTotal =0f;
                LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
                wp.eq(StationInfo::getUserType,1).eq(StationInfo::getLineId,record.getLineId());
                List<StationInfo> subs = stationInfoMapper.selectList(wp);
                List<Integer> no_list = subs.stream().map(StationInfo::getStationNo).collect(Collectors.toList());
                Float startTotal_start = realdataMapper.getSubTotal(no_list,start,start.plusMinutes(5));
                Float startTotal_end = realdataMapper.getSubTotal(no_list,end,end.plusMinutes(5));
                if (startTotal_end != null || startTotal_start != null){
                    subTotal = startTotal_end - startTotal_start;
                }else {
                    subTotal = 0f;
                }
//                for (StationInfo sub : subs) {
//                    Integer subNo = sub.getStationNo();
//                    Realdata sub1 = realdataMapper.historySelectOne(subNo, start, start.plusMinutes(5));
//                    if(sub1==null){
//                        continue;
//                    }
//                    Realdata sub2 = realdataMapper.historySelectOne(subNo, end.minusMinutes(1), end.plusMinutes(5));
//                    if(sub2==null){
//                        continue;
//                    }
//                    subTotal +=(sub2.getTotal()-sub1.getTotal());
//                }
                //查找该分节点的消耗总结,相减计算管损和管损率
                float loss = total - subTotal;
                map.put("管损",String.format("%.2f",loss));
                if (total!=0f){
                    map.put("管损率",String.format("%.2f",loss*100/total) +"%");
                }else{
                    map.put("管损率","--");
                }
            }else{
                map.put("管损",null);
                map.put("管损率",null);
            }
            res.add(map);
        }
        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(res, true);
        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,res);

        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode( "自定义用量报表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);

    }

    /**
     * 单用户自定义报表
     * @param stationNo
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getTablePeriod(Integer stationNo, Integer pageNo,LocalDateTime start,LocalDateTime end) {
        PagedResult pagedResult = new PagedResult();

        Page<StationInfo> page = new Page<>(pageNo, 10);
        long totalRecord = ChronoUnit.MINUTES.between(start, end);

        pagedResult.setTotal(totalRecord);
        pagedResult.setPages(totalRecord/10+1);

        start = start.plusMinutes((pageNo-1)*10);

        ArrayList<Map<String,Object>> res = new ArrayList<>();
        for (int i=0;i<10;i++) {
            HashMap<String, Object> map = new LinkedHashMap<>();
            Realdata realdata = realdataMapper.historySelectOne(stationNo, start, start.plusMinutes(2));
            if(realdata!=null){
                map.put("流量(t/h)",realdata.getFlow());
                map.put("温度(°C)",realdata.getTemp());
                map.put("压力(Mpa)",realdata.getPres());
                map.put("总量(t)",realdata.getTotal());
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                map.put("时间",start.format(dateTimeFormatter));
            }else{
                map.put("流量(t/h)",0);
                map.put("温度(°C)",0);
                map.put("压力(Mpa)",0);
                map.put("总量(t)",0);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                map.put("时间",start.format(dateTimeFormatter));
            }
            start = start.plusMinutes(1);
            res.add(map);
        }
        pagedResult.setRows(res);
        return pagedResult;
    }

    @Override
    public void getTablePeriodExcel(Integer stationNo, LocalDateTime start, LocalDateTime end,HttpServletResponse response) throws IOException {
        ArrayList<Map<String,Object>> res = new ArrayList<>();
        while(start.compareTo(end)<=0){
            HashMap<String, Object> map = new LinkedHashMap<>();
            Realdata realdata = realdataMapper.historySelectOne(stationNo, start, start.plusMinutes(2));
            if(realdata!=null){
                map.put("流量(t/h)",realdata.getFlow());
                map.put("温度(°C)",realdata.getTemp());
                map.put("压力(Mpa)",realdata.getPres());
                map.put("总量(t)",realdata.getTotal());
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                map.put("时间",start.format(dateTimeFormatter));
            }else{
                map.put("流量(t/h)",0);
                map.put("温度(°C)",0);
                map.put("压力(Mpa)",0);
                map.put("总量(t)",0);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                map.put("时间",start.format(dateTimeFormatter));
            }
            start = start.plusMinutes(1);
            res.add(map);
        }
        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(res, true);
        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,res);

        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode( "自定义用量报表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);

    }

    @Override
    public List<SomeStationFlowTotal> getThreeTablePeriod(LocalDateTime start, LocalDateTime end) {

        List<SomeStationFlowTotal> res = new ArrayList<>();

        LambdaQueryWrapper<StationInfo> wp1 = new LambdaQueryWrapper<>();
        wp1.eq(StationInfo::getIsUse,true).orderByAsc(StationInfo::getStationNo);
        List<StationInfo> records = stationInfoMapper.selectList(wp1);


        List<Integer> stations = records.stream().map(StationInfo::getStationNo).collect(Collectors.toList());
        System.out.println("第一次开始请求sharding" + new Date());
        List<Realdata> history_start = realdataMapper.historySelectAll(stations, start, start.plusMinutes(5));
        System.out.println("第一次结束请求sharding第二次开始" + new Date());
        List<Realdata> history_end = realdataMapper.historySelectAll(stations, end.plusMinutes(1), end.plusMinutes(5));
        System.out.println("第二次结束请求sharding"+ new Date());
        Map<Integer, Realdata> start_map = history_start.stream().collect(Collectors.toMap(
                Realdata::getStation,
                realdata -> realdata));
        Map<Integer, Realdata> end_map = history_end.stream().collect(Collectors.toMap(
                Realdata::getStation,
                realdata -> realdata));
        SomeStationFlowTotal someStationFlowTotalHigh = new SomeStationFlowTotal("电厂合计流量（高压）",0f,0f,0f);
        SomeStationFlowTotal someStationFlowTotalLow = new SomeStationFlowTotal("电厂合计流量（低压）",0f,0f,0f);
        SomeStationFlowTotal elseStationFlowTotalHigh = new SomeStationFlowTotal("所有用户合计流量（高压）",0f,0f,0f);
        SomeStationFlowTotal elseStationFlowTotalLow = new SomeStationFlowTotal("所有用户合计流量（低压）",0f,0f,0f);
        List<Integer> threeStationHighNo = new ArrayList<>(java.util.Arrays.asList(331, 350, 458));
        List<Integer> threeStationLowNo = new ArrayList<>(java.util.Arrays.asList(332, 351));


        for (StationInfo record : records) {
            Realdata realdata1 =start_map.get(record.getStationNo());
            if (threeStationHighNo.contains(record.getStationNo())) {
                if (realdata1 != null && realdata1.getFlow() != null) {
                    someStationFlowTotalHigh.setStartNum(someStationFlowTotalHigh.getStartNum() + realdata1.getFlow());
                }
            }else if (threeStationLowNo.contains(record.getStationNo())) {
                if (realdata1 != null && realdata1.getFlow() != null) {
                    someStationFlowTotalLow.setStartNum(someStationFlowTotalLow.getStartNum() + realdata1.getFlow());
                }
            }else {
                if(record.getLineId() == 24){
                    if (realdata1 != null && realdata1.getFlow() != null) {
                        elseStationFlowTotalHigh.setStartNum(elseStationFlowTotalHigh.getStartNum() + realdata1.getFlow());
                    }
                } else if (record.getLineId() == 25) {
                    if (realdata1 != null && realdata1.getFlow() != null) {
                        elseStationFlowTotalLow.setStartNum(elseStationFlowTotalLow.getStartNum() + realdata1.getFlow());
                    }
                }
            }

            Realdata realdata2 =end_map.get(record.getStationNo());
            if (threeStationHighNo.contains(record.getStationNo())) {
                if (realdata2 != null && realdata2.getFlow() != null) {
                    someStationFlowTotalHigh.setEndNum(someStationFlowTotalHigh.getEndNum() + realdata2.getFlow());
                }
                someStationFlowTotalHigh.setBetween(someStationFlowTotalHigh.getEndNum() - someStationFlowTotalHigh.getStartNum());
            }else if (threeStationLowNo.contains(record.getStationNo())) {
                if (realdata2 != null && realdata2.getFlow() != null) {
                    someStationFlowTotalLow.setEndNum(someStationFlowTotalLow.getEndNum() + realdata2.getFlow());
                    }
                someStationFlowTotalLow.setBetween(someStationFlowTotalLow.getEndNum() - someStationFlowTotalLow.getStartNum());
            }else {
                if(record.getLineId() == 24){
                    if (realdata2 != null && realdata2.getFlow() != null) {
                        elseStationFlowTotalHigh.setEndNum(elseStationFlowTotalHigh.getEndNum() + realdata2.getFlow());
                    }
                    elseStationFlowTotalHigh.setBetween(elseStationFlowTotalHigh.getEndNum() - elseStationFlowTotalHigh.getStartNum());
                } else if (record.getLineId() == 25) {
                    if (realdata2 != null && realdata2.getFlow() != null) {
                        elseStationFlowTotalLow.setEndNum(elseStationFlowTotalLow.getEndNum() + realdata2.getFlow());
                    }
                    elseStationFlowTotalLow.setBetween(elseStationFlowTotalLow.getEndNum() - elseStationFlowTotalLow.getStartNum());
                }
            }

        }
        res.add(someStationFlowTotalHigh);
        res.add(someStationFlowTotalLow);
        res.add(elseStationFlowTotalHigh);
        res.add(elseStationFlowTotalLow);
        return res;
    }


}




